/**
 * 
 */
package com.core.util;

import java.io.Serializable;

import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Transactional;

/**
 * = Restrictions.eq() 等于 
<> Restrictions.not(Exprission.eq()) 不等于 
> Restrictions.gt() 大于 
>= Restrictions.ge() 大于等于 
< Restrictions.lt() 小于 
<= Restrictions.le() 小于等于 
is null Restrictions.isnull() 等于空值 
is not null Restrictions.isNotNull() 非空值 
like Restrictions.like() 字符串模式匹配 
and Restrictions.and() 逻辑与 
and Restrictions.conjunction() 逻辑与 
or Restrictions.or() 逻辑或 
or Restrictions.disjunction() 逻辑或 
not Restrictions.not() 逻辑非 
in(列表) Restrictions.in() 等于列表中的某一个值 
ont in(列表) Restrictions.not(Restrictions.in())不等于列表中任意一个值 
between x and y Restrictions.between() 闭区间xy中的任意值 
not between x and y Restrictions.not(Restrictions..between()) 小于值X或者大于值y
 * @author dsp.coding
 * 
 */
public class GenericDAOHibernate<T, PK extends Serializable> extends HibernateDaoSupport implements GenericDAO<T, PK> {

	private Class<T> clazz;

	public GenericDAOHibernate(Class<T> clazz) {
		this.clazz = clazz;
	}

	@SuppressWarnings("unchecked")
	public GenericDAOHibernate() {
		this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	@Override
	public boolean delete(T entry) {
		getHibernateTemplate().delete(entry);
		return true;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional
	public List<T> findAll(T entry , final int firstResult, final int maxResults) {
		List<T> list = null;
		try {
			list = getHibernateTemplate().findByExample(entry , firstResult, maxResults);
		} catch (DataAccessException e) {
			e.printStackTrace();
		}  
		return list;
	}

	@Transactional
	public Long getTotalCount(T entry) {
		Long count = (Long)getHibernateTemplate().find(" select count(id) from "+ this.clazz.getName()).listIterator().next();
		return count;
	}

	@Override
	public T findById(PK id) {
		return (T) getHibernateTemplate().get(this.clazz, id);
	}

	@Override
	public void save(T entry) {
		getHibernateTemplate().save(entry);
	}

	@Override
	public boolean update(T entry) {
		getHibernateTemplate().update(entry);
		return true;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional
	public List<T> getCondition(T entry) {
		return getHibernateTemplate().findByExample(entry);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	@Transactional
	public Pagination<T> search(final DetachedCriteria dc,final int firstResult,final int maxResults) {
//		return getHibernateTemplate().findByCriteria(dc, firstResult, maxResults);
		return (Pagination<T>)getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public  Object doInHibernate(Session session) throws HibernateException, SQLException {
				Criteria criteria = dc.getExecutableCriteria(session);
				int totalCount = ((Integer)criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
				criteria.setProjection(null);
				List<T> list = criteria.setFirstResult(firstResult).setMaxResults(maxResults).list();
				Pagination<T> p = new Pagination<T>(list, totalCount,maxResults);
				return p;
			}
		});
	}

	@Override
	@Transactional
	public Long getTotalCount(DetachedCriteria dc) {
		dc.setProjection(Projections.rowCount());
		Integer row = (Integer)getHibernateTemplate().findByCriteria(dc).get(0);
		dc.setProjection(null);
		return row.longValue();
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional
	public List<T> likeBy(DetachedCriteria dc) {
		return getHibernateTemplate().findByCriteria(dc);
		/**
		return (List<User>) getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public List doInHibernate(Session arg0) throws HibernateException, SQLException {
				Criteria criteria = dc.getExecutableCriteria(arg0);
				return  criteria.list();
			}
		}); **/
	}
}